package OJPractice;
/*单例模式中的饿汉模式
* 将构造器私有化就不能创建新的实例了，此时*/
class Singleton {
    private static Singleton instance = new Singleton();
    // 获取这个类的唯一一个实例的方法
    public static Singleton getInstance() {
        return instance;
    }
    // 将构造器私有化
    private Singleton() { }
}

class SingletonLazy {
    // 也就是说此时先不创建实例，当调用这个获取实例方法的时候再去创建实例
    private static SingletonLazy instance = null;

    public static SingletonLazy getInstance() {
        /*
        * 此时这里用双重if判断的原因：锁中的if 判定是为了看这个实例是否被创建过
        * 锁外边的 if 判断是为了 提高效率，因为里边的if判定和实例的创建不是原子操作，
        * 所以涉及到线程安全问题，此时就需要加锁，但是加锁就会降低效率，此时可以看下：
        * 只有第一次创建实例对象的时候是需要枷锁的，之后把实例创建出来之后就不需要加锁了
        * 所以此时在 锁 外边在加一个 if 判定，如果这个实例已经被创建出来了，此时就不进入 if 了
        * 此时也就没有加锁的成本了
        * */
        if (instance == null) {
            synchronized (SingletonLazy.class) {
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
}
public class ThreadDemo1 {
    // 单例模式中的懒汉模式
    public static void main(String[] args) {
         // 此时通过这个类中的获取实例的方法获取到的两个实例其实也是同一个对象
        SingletonLazy s1 = SingletonLazy.getInstance();
        SingletonLazy s2 = SingletonLazy.getInstance();
        System.out.println(s1 == s2);
    }

    // 单例模式中的饿汉模式
    public static void main1(String[] args) {
        // 此时这两个引用获取的实例是同一个实例
        Singleton s1 = Singleton.getInstance();
        Singleton s2 = Singleton.getInstance();
        System.out.println(s1 == s2);

        // 此时下面代码会报错
        // Singleton s3 = new Singleton();
    }
}
